using System;
using System.Diagnostics;
using System.IO;
using System.Xml;
namespace QuanLyDiemSinhVien.Logger
{
    //Author : Mohamed Ashraf
    //Date Written : 9th April 2003
    //Date Modified: 14th April 2003
    /// <summary>
    /// Logger is used for creating a customized error log files or an error can be registered as
    /// a log entry in the Windows Event Log on the administrator's machine.
    /// </summary>
    public class ErrorLog
    {
        protected static string StrLogFilePath = string.Empty;
        protected static string StrEventLogName = "ErrorSample";
        private static StreamWriter _sw;
        public delegate void LogUpdatedEventHandler();

        // Declare the event.
        public static event LogUpdatedEventHandler LogUpdatedEvent;

        private static void RaiseLogUpdatedEvent()
        {
            LogUpdatedEvent();
        }

        /// <summary>
        /// Setting LogFile path. If the logfile path is null then it will update error info into LogFile.txt under
        /// application directory.
        /// </summary>

        public static string LogFilePath
        {
            set
            {
                StrLogFilePath = value;
            }
            get
            {
                return StrLogFilePath;
            }
        }

        public static string EventLogName
        {
            set
            {
                StrEventLogName = value;
            }
            get
            {
                return StrEventLogName;
            }
        }

        /// <summary>
        /// Write error log entry for window event if the bLogType is true. Otherwise, write the log entry to
        /// customized text-based text file
        /// </summary>
        /// <param name="bLogType"></param>
        /// <param name="objException"></param>
        /// <returns>false if the problem persists</returns>
        public static bool ErrorRoutine(bool bLogType, Exception objException)
        {
            try
            {
                bool bLoggingEnabled = CheckLoggingEnabled();

                //Don't process more if the logging 
                if (false == bLoggingEnabled)
                    return true;

                //Write to Windows event log
                if (bLogType)
                {
                    if (!EventLog.SourceExists(EventLogName))
                        EventLog.CreateEventSource(objException.Message, EventLogName);

                    // Inserting into event log
                    var log = new EventLog {Source = EventLogName};
                    log.WriteEntry(objException.Message, EventLogEntryType.Error);
                }
                //Custom text-based event log
                else
                {
                    if (true != CustomErrorRoutine(objException))
                        return false;
                }

                RaiseLogUpdatedEvent();

                return true;

            }
            catch (Exception)
            {
                return false;
            }
        }

        public static string GetLogContents()
        {
            try
            {
                var sr = new StreamReader(GetLogFilePath());
                sr.Read();
                string strFileContent = sr.ReadToEnd();
                sr.Close();
                return strFileContent;
            }
            catch (Exception)
            {
                return "";
            }
        }
        /// <summary>
        /// Check Logginstatus config file is exist. If exist read the value set the loggig status
        /// </summary>
        private static bool CheckLoggingEnabled()
        {
            string strLoggingStatusConfig = GetLoggingStatusConfigFileName();

            //If it's empty then enable the logging status 
            if (strLoggingStatusConfig.Equals(string.Empty))
            {
                return true;
            }
            //Read the value from xml and set the logging status
            bool bTemp = GetValueFromXml(strLoggingStatusConfig);
            return bTemp;
        }

        /// <summary>
        /// Check the Logginstatus config under debug or release folder. If not exist, check under 
        /// project folder. If not exist again, return empty string
        /// </summary>
        /// <returns>empty string if file not exists</returns>
        private static string GetLoggingStatusConfigFileName()
        {
            string strCheckinBaseDirecotry = AppDomain.CurrentDomain.BaseDirectory + "LoggingStatus.Config";

            if (File.Exists(strCheckinBaseDirecotry))
                return strCheckinBaseDirecotry;
            else
            {
                string strCheckinApplicationDirecotry = GetApplicationPath() + "LoggingStatus.Config";

                if (File.Exists(strCheckinApplicationDirecotry))
                    return strCheckinApplicationDirecotry;
                else
                    return string.Empty;
            }
        }
        /// <summary>
        /// Read the xml file and getthe logging status
        /// </summary>
        /// <param name="strXmlPath"></param>
        /// <returns></returns>
        private static bool GetValueFromXml(string strXmlPath)
        {
            try
            {
                //Open a FileStream on the Xml file
                var docIn = new FileStream(strXmlPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                var contactDoc = new XmlDocument();
                //Load the Xml Document
                contactDoc.Load(docIn);

                //Get a node
                XmlNodeList userList = contactDoc.GetElementsByTagName("LoggingEnabled");

                //get the value
                string strGetValue = userList.Item(0).InnerText;

                if (strGetValue.Equals("0"))
                    return false;
                else if (strGetValue.Equals("1"))
                    return true;
                else
                    return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// If the LogFile path is empty then, it will write the log entry to LogFile.txt under application directory.
        /// If the LogFile.txt is not availble it will create it
        /// If the Log File path is not empty but the file is not availble it will create it.
        /// </summary>
        /// <param name="objException"></param>
        /// <returns>false if the problem persists</returns>
        private static bool CustomErrorRoutine(Exception objException)
        {
            string strPathName;
            if (StrLogFilePath.Equals(string.Empty))
            {
                //Get Default log file path "LogFile.txt"
                strPathName = GetLogFilePath();
            }
            else
            {
                //If the log file path is not empty but the file is not available it will create it
                if (false == File.Exists(StrLogFilePath))
                {
                    if (false == CheckDirectory(StrLogFilePath))
                        return false;
                    var fs = new FileStream(StrLogFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    fs.Close();
                }
                strPathName = StrLogFilePath;
            }

            bool bReturn = true;
            // write the error log to that text file
            if (true != WriteErrorLog(strPathName, objException))
            {
                bReturn = false;
            }
            return bReturn;
        }

        public static bool ClearLog()
        {
            string sfilepath = GetLogFilePath();
            try
            {
                if (File.Exists(sfilepath))
                {
                    var sw = new StreamWriter(sfilepath);
                    sw.Write(string.Empty);
                    sw.Close();
                    return true;
                }
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Write Source,method,date,time,computer,error and stack trace information to the text file
        /// </summary>
        /// <param name="strPathName"></param>
        /// <param name="objException"></param>
        /// <returns>false if the problem persists</returns>
        private static bool WriteErrorLog(string strPathName, Exception objException)
        {
            bool bReturn;
            _sw = new StreamWriter(strPathName, true);

            if (objException.StackTrace == null)
            {
                try
                {
                    _sw.WriteLine("");
                    _sw.WriteLine("Error		: " + objException.Message.Trim());
                    _sw.WriteLine("-------------------------------------------------------------------");
                    _sw.Flush();
                    _sw.Close();
                    bReturn = true;
                }
                catch (Exception)
                {
                    _sw.Close();
                    bReturn = false;
                }
            }
            else
            {
                try
                {
                    _sw.WriteLine("Source		: " + objException.Source.Trim());
                    _sw.WriteLine("Method		: " + objException.TargetSite.Name);
                    _sw.WriteLine("Date		: " + DateTime.Now.ToLongTimeString());
                    _sw.WriteLine("Time		: " + DateTime.Now.ToShortDateString());
                    _sw.WriteLine("Error		: " + objException.Message.Trim());
                    _sw.WriteLine("Stack Trace	: " + objException.StackTrace);
                    _sw.WriteLine("-------------------------------------------------------------------");
                    _sw.Flush();
                    _sw.Close();
                    bReturn = true;
                }
                catch (Exception)
                {
                    _sw.Close();
                    bReturn = false;
                }
            }

            return bReturn;

        }
        /// <summary>
        /// Check the log file in applcation directory. If it is not available, creae it
        /// </summary>
        /// <returns>Log file path</returns>
        private static string GetLogFilePath()
        {
            try
            {
                // get the base directory
                string baseDir = AppDomain.CurrentDomain.BaseDirectory;

                // search the file below the current directory
                string retFilePath = baseDir + "\\" + "LogFile.txt";

                // if exists, return the path
                if (File.Exists(retFilePath))
                    return retFilePath;
                //create a text file
                else
                {
                    if (false == CheckDirectory(retFilePath))
                        return string.Empty;

                    var fs = new FileStream(retFilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
                    fs.Close();
                }

                return retFilePath;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }
        /// <summary>
        /// Create a directory if not exists
        /// </summary>
        /// <param name="strLogPath"></param>
        /// <returns></returns>
        private static bool CheckDirectory(string strLogPath)
        {
            try
            {
                int nFindSlashPos = strLogPath.Trim().LastIndexOf("\\");
                string strDirectoryname = strLogPath.Trim().Substring(0, nFindSlashPos);

                if (false == Directory.Exists(strDirectoryname))
                    Directory.CreateDirectory(strDirectoryname);

                return true;
            }
            catch (Exception)
            {
                return false;

            }
        }

        private static string GetApplicationPath()
        {
            try
            {
                string strBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
                int nFirstSlashPos = strBaseDirectory.LastIndexOf("\\");
                string strTemp = string.Empty;

                if (0 < nFirstSlashPos)
                    strTemp = strBaseDirectory.Substring(0, nFirstSlashPos);

                int nSecondSlashPos = strTemp.LastIndexOf("\\");
                string strTempAppPath = string.Empty;
                if (0 < nSecondSlashPos)
                    strTempAppPath = strTemp.Substring(0, nSecondSlashPos);

                string strAppPath = strTempAppPath.Replace("bin", "");
                return strAppPath;
            }
            catch (Exception)
            {
                return string.Empty;
            }
        }
    }
}
